
package com.hlkj.pay.app.user.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.math.BigDecimal;
import java.time.LocalDateTime;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.common.IAuthCodeService;
import com.hlkj.pay.app.order.impl.OrderHandler;
import com.hlkj.pay.app.token.ITokenAuthService;
import com.hlkj.pay.app.user.IUserAppService;
import com.hlkj.pay.common.CommonResultCode;
import com.hlkj.pay.common.UserResultCode;
import com.hlkj.pay.enums.AdminUserEnum;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.enums.UserEnum;
import com.hlkj.pay.infrastructure.model.ad.AdInfoConfigDO;
import com.hlkj.pay.infrastructure.model.user.UserCouponDO;
import com.hlkj.pay.infrastructure.model.user.UserDO;
import com.hlkj.pay.infrastructure.model.user.UserTeleChargeOrderDO;
import com.hlkj.pay.service.ad.IAdInfoService;
import com.hlkj.pay.service.user.IUserCouponService;
import com.hlkj.pay.service.user.IUserRechargeService;
import com.hlkj.pay.service.user.IUserService;
import com.hlkj.pay.util.DateUtils;
import com.hlkj.pay.util.OrderCodeUtil;
import com.hlkj.pay.vo.admin.req.user.AdminAuthCodeReq;
import com.hlkj.pay.vo.common.req.CommonUpdateStatusReq;
import com.hlkj.pay.vo.common.req.token.PhoneTokenRequest;
import com.hlkj.pay.vo.common.resp.token.OauthTokenResp;
import com.hlkj.pay.vo.user.req.UseChargeReq;
import com.hlkj.pay.vo.user.req.UseLoginReq;
import com.hlkj.pay.vo.user.req.UserTeleChargeOrderReq;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2024/10/25 14:44
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserAppServiceImpl implements IUserAppService {

    private final IUserService userService;

    private final IUserRechargeService userRechargeService;

    private final IAuthCodeService authCodeService;

    private final ITokenAuthService tokenAuthService;

    private final OrderHandler orderHandler;

    private final OrderCodeUtil orderCodeUtil;

    private final IUserCouponService userCouponService;

    private final IAdInfoService adInfoService;

    @Override
    public CommonResult<Void> sendAuthCode(String phone) {
        log.info("sendAuthCode phone:{}", phone);
        try {
            UserDO userDO = userService.queryUserByPhone(phone);
            if (userDO == null) {
                return CommonResult.error(UserResultCode.USER_NOT_EXITS);
            }
            AdminAuthCodeReq adminAuthCodeReq = new AdminAuthCodeReq();
            adminAuthCodeReq.setPhone(phone);
            adminAuthCodeReq.setBusinessScenario(AdminUserEnum.AdminAuthCodeEnum.AUTH_CODE_LOGIN.getCode());
            return authCodeService.sendAuthCode(adminAuthCodeReq);
        }
        catch (Exception e) {
            log.error("sendAuthCode fail message:{}", e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<OauthTokenResp> login(UseLoginReq useLoginReq) {
        PhoneTokenRequest phoneTokenRequest = new PhoneTokenRequest();
        phoneTokenRequest.setPhone(useLoginReq.getPhone());
        phoneTokenRequest.setSmsCode(useLoginReq.getAuthCode());
        return tokenAuthService.clientToken(phoneTokenRequest);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Void> charge(Long userId, UseChargeReq useChargeReq) {
        log.info("charge useChargeReq:{}", JsonUtils.toJsonString(useChargeReq));
        try {
            UserTeleChargeOrderDO userTeleChargeOrderLast = userRechargeService.queryRechargeOrderLast(userId);
            if (userTeleChargeOrderLast != null && (userTeleChargeOrderLast.getState() != 4 && userTeleChargeOrderLast.getState() != 7)) {
                return CommonResult.error(UserResultCode.USER_RECHARGE_EXITS);
            }
            if (useChargeReq.getUserCouponId() != null) {
                UserCouponDO userCouponDO = userCouponService.queryUserCoupon(useChargeReq.getUserCouponId());
                if (userCouponDO == null) {
                    return CommonResult.error(UserResultCode.USER_COUPON_NOT_EXITS);
                }
                if (!UserEnum.USER_COUPON_STATUS.NO_USE.getCode().equals(userCouponDO.getStatus())) {
                    return CommonResult.error(UserResultCode.USER_COUPON_NOT_EFFECT);
                }
                UserTeleChargeOrderDO userTeleChargeOrderDO = userRechargeService.queryCouponRechargeOrderLast(userId);
                // 上一笔没用过优惠劵
                if (userTeleChargeOrderDO != null && (userCouponDO.getRelationId() != null)) {
                    AdInfoConfigDO adInfoConfigDO = adInfoService.queryConfigByAdId(userCouponDO.getRelationId());
                    boolean check = true;
                    String message = "";
                    if (adInfoConfigDO.getCouponUseLimit() != null) {
                        LocalDateTime now = LocalDateTime.now();
                        LocalDateTime localDateTime = DateUtils.dateToLocalDateTime(userTeleChargeOrderDO.getCreateTime());
                        // 0 无限制 1 每周一次 2 每月一次
                        switch (adInfoConfigDO.getCouponUseLimit()) {
                            case 0:
                                break;
                            case 1:
                                if (DateUtils.isSameDay(localDateTime, now)) {
                                    check = false;
                                    message = "天";
                                }
                                break;
                            case 2:
                                if (DateUtils.isSameWeek(localDateTime, now)) {
                                    check = false;
                                    message = "周";
                                }
                                break;
                            case 3:
                                if (DateUtils.isSameMonth(localDateTime, now)) {
                                    check = false;
                                    message = "月";
                                }
                                break;
                        }
                    }
                    if (!check) {
                        return CommonResult.error(UserResultCode.USER_COUPON_USE_LIMIT.getCode(), String.format(UserResultCode.USER_COUPON_USE_LIMIT.getMsg(), message));
                    }
                }
                userCouponService.updateCouponStatus(userCouponDO.getId(), UserEnum.USER_COUPON_STATUS.USED);
            }
            UserTeleChargeOrderDO userTeleChargeOrderDO = new UserTeleChargeOrderDO();
            userTeleChargeOrderDO.setChargeNo(orderCodeUtil.orderNo(PayOrderEnums.ORDER_NO_TYPE.RECHARGE_APPLY));
            userTeleChargeOrderDO.setUserId(userId);
            userTeleChargeOrderDO.setPhone(useChargeReq.getPhone());
            userTeleChargeOrderDO.setRechargeAmount(new BigDecimal(useChargeReq.getAmount()));
            userTeleChargeOrderDO.setState(UserEnum.RECHARGE_STATUS.WAIT_PAY.getCode());
            userTeleChargeOrderDO.setUserCouponId(useChargeReq.getUserCouponId());
            userRechargeService.addRechargeOrder(userTeleChargeOrderDO);
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("charge fail message:{}",e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> updateRechargeStatus(UserTeleChargeOrderReq userTeleChargeOrderReq) {
        log.info("updateRechargeStatus userTeleChargeOrderReq:{}", JsonUtils.toJsonString(userTeleChargeOrderReq));
        try {
            UserTeleChargeOrderDO userTeleChargeOrderDO = userRechargeService.queryDetail(userTeleChargeOrderReq.getChargeNo());
            if (userTeleChargeOrderDO == null) {
                return CommonResult.error(UserResultCode.USER_RECHARGE_NOT_EXITS);
            }
            UserTeleChargeOrderDO updateUserTeleChargeOrderDO = new UserTeleChargeOrderDO();
            updateUserTeleChargeOrderDO.setState(userTeleChargeOrderReq.getState());
            updateUserTeleChargeOrderDO.setThirdRechargeId(userTeleChargeOrderReq.getThirdRechargeId());
            updateUserTeleChargeOrderDO.setRemark(userTeleChargeOrderReq.getRemark());
            updateUserTeleChargeOrderDO.setId(userTeleChargeOrderDO.getId());
            userRechargeService.updateChargeOrder(updateUserTeleChargeOrderDO);
            // 充值失败退劵
            if (userTeleChargeOrderReq.getState() == 7 && userTeleChargeOrderDO.getUserCouponId() != null) {
                log.info("充值失败退劵 userCouponId:{}", userTeleChargeOrderDO.getUserCouponId());
                userCouponService.updateCouponStatus(userTeleChargeOrderDO.getUserCouponId(), UserEnum.USER_COUPON_STATUS.NO_USE);
            }
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("updateRechargeStatus fail message:{}", e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> updateUserStatus(CommonUpdateStatusReq commonUpdateStatusReq) {
        log.info("updateUserStatus commonUpdateStatusReq:{}", JsonUtils.toJsonString(commonUpdateStatusReq));
        try {
            UserDO userDO = userService.queryUserById(commonUpdateStatusReq.getId());
            if (userDO == null) {
                return CommonResult.error(UserResultCode.USER_NOT_EXITS);
            }
            userDO.setStatus(commonUpdateStatusReq.getStatus());
            userService.updateUser(userDO);
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("updateUserStatus fail message:{}", e, e.getMessage());
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }
}
